﻿using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Security.Cryptography;
using System.Text;
using Microsoft.AspNetCore.Authentication;
using System.IO;
using System.IO.Compression;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http.Headers;
using SixLabors.ImageSharp.Processing;
using SixLabors.ImageSharp;

namespace housingsafety.server.Helpers
{
    public static class UtilExtenions
    {
        public static void Thumbnail(string inImag, string outImg, int width = 128, int height = 128)
        {
            var file = new FileInfo(inImag);
            Console.WriteLine("Bytes before: " + file.Length);
            //缩略图
            using (SixLabors.ImageSharp.Image image = SixLabors.ImageSharp.Image.Load(inImag))
            {
                image.Mutate(x => x
                     .Resize(width, height)
                     .Grayscale());
                image.Save(outImg);
            }

            Console.WriteLine("Bytes after:  " + new FileInfo(outImg).Length);
        }

        /// <summary>
        /// 生成缩略图
        /// </summary>
        /// <param name="objectStream"></param>
        /// <param name="outImg"></param>
        /// <param name="side"></param>
        public static void Thumbnail(Stream objectStream, string outImg, int side = 256)
        {
            Console.WriteLine("Bytes before: " + objectStream.Length);
            //缩略图
            using (Image image = Image.Load(objectStream))
            {
                if (image.Width <= side && image.Height <= side)
                {
                    image.Save(outImg);
                }
                else
                {                    //宽大于高的横图
                    if (image.Width > image.Height)
                    {
                        Rectangle cropRectangle = new Rectangle((image.Width - image.Height) / 2
                            , 0, image.Height, image.Height);
                        image.Mutate(x => x
                            .Crop(cropRectangle)
                            .Resize(side, side));
                    }
                    //高大于宽的竖图
                    else
                    {
                        Rectangle cropRectangle = new Rectangle(0
                            , (image.Height - image.Width) / 2, image.Width, image.Width);
                        image.Mutate(x => x
                            .Crop(cropRectangle)
                            .Resize(side, side));
                    }

                    image.Save(outImg);
                }
            }

            Console.WriteLine("Bytes after:  " + new FileInfo(outImg).Length);
        }
        public static void Luban(Stream objectStream, string outImg, int width = 128, int height = 128)
        {
            Console.WriteLine("Bytes before: " + objectStream.Length);
            //缩略图
            new Luban(objectStream)
            {
                IgnoreBy = 102400,
                Quality = 60
            }
                .Compress(outImg);

            Console.WriteLine("Bytes after:  " + new FileInfo(outImg).Length);
        }

        public static async Task BuildZip(string backupZipFile, string readme, string folder)
        {
            var files = Directory.GetFiles(folder)
                .ToDictionary(Path.GetFileName);

            await BuildZip(backupZipFile, readme, files);
        }
        public static async Task BuildZip(string backupZipFile, string readme, Dictionary<string, string> files)
        {
            if (files.Count > 0)
            {
                using (FileStream zipToOpen = new FileStream(backupZipFile, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite))
                {
                    using (ZipArchive archive = new ZipArchive(zipToOpen, ZipArchiveMode.Create))
                    {
                        ZipArchiveEntry readmeEntry = archive.CreateEntry("readme.txt");
                        using (StreamWriter writer = new StreamWriter(readmeEntry.Open()))
                        {
                            await writer.WriteLineAsync("Information about this package.");
                            await writer.WriteLineAsync(readme);
                        }

                        foreach (var file in files)
                        {
                            if (File.Exists(file.Value))
                            {
                                ZipArchiveEntry sqlEntry = archive.CreateEntry(file.Key);
                                using (FileStream fs = File.Open(file.Value, FileMode.Open, FileAccess.Read,
                                    FileShare.ReadWrite))
                                {
                                    var destination = sqlEntry.Open();
                                    await fs.CopyToAsync(destination);

                                    await destination.FlushAsync();
                                    destination.Close();
                                    await destination.DisposeAsync();
                                }
                            }
                        }
                    }
                }
            }
        }
        public static string GetGateWayUrl(this HttpContext context)
        {
            IHttpContextAccessor httpContextAccessor = (IHttpContextAccessor)context.RequestServices
                .GetService(typeof(IHttpContextAccessor));

            string host = httpContextAccessor.HttpContext.Request.GetTypedHeaders().Referer.Authority;

            return (new StringBuilder()
                .Append(context.Request.Scheme)
                .Append("://")
                .Append(host)
                .Append(context.Request.PathBase)
                .ToString());
        }

        public static void WriteErrorConsoleLine(string value)
        {
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine($"error: {value}");
            Console.ResetColor();
        }
        public static string Md5(this string originString)
        {
            var md5 = MD5.Create();

            var bs = md5.ComputeHash(Encoding.UTF8.GetBytes(originString));
            var sb = new StringBuilder();

            foreach (byte b in bs)
            {
                sb.Append(b.ToString("x2"));
            }

            md5.Dispose();

            return sb.ToString();
        }
        public static string Sha256(this string originString)
        {
            var md5 = SHA256.Create();

            var bs = md5.ComputeHash(Encoding.UTF8.GetBytes(originString));
            var sb = new StringBuilder();

            foreach (byte b in bs)
            {
                sb.Append(b.ToString("x2"));
            }

            md5.Dispose();

            return sb.ToString();
        }

        public static string Md5(this Stream inputStream)
        {
            var md5 = MD5.Create();

            var bs = md5.ComputeHash(inputStream);
            var sb = new StringBuilder();

            foreach (byte b in bs)
            {
                sb.Append(b.ToString("x2"));
            }

            md5.Dispose();

            return sb.ToString();
        }

        public static string GenerateRandomNumber(int Length)
        {
            System.Text.StringBuilder newRandom = new System.Text.StringBuilder(Length);
            Random rd = new Random();
            for (int i = 0; i < Length; i++)
            {
                newRandom.Append(rd.Next(0, 9));
            }
            return newRandom.ToString();
        }

        public static void WriteWarnConsoleLine(string value)
        {
            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine($"warn: {value}");
            Console.ResetColor();
        }

        public static bool IsMobilePhone(string strHandset)
        {
            return System.Text.RegularExpressions.Regex.IsMatch(strHandset, @"^[1]+[3,5,7,8]+\d{9}");
        }

        public static bool ContainsSqlInjection(string str)
        {
            if (string.IsNullOrEmpty(str))
                return false;
            var chk = str.Contains("'") ||
            str.Contains(" ") ||
            str.Contains(";") ||
            str.Contains(",") ||
            str.Contains("?") ||
            str.Contains("<") ||
            str.Contains(">") ||
            str.Contains("(") ||
            str.Contains(")") ||
            str.Contains("@") ||
            str.Contains("=") ||
            str.Contains("+") ||
            str.Contains("*") ||
            str.Contains("&") ||
            str.Contains("#") ||
            str.Contains("%") ||
            str.Contains("$");

            return chk;
        }

        public static string CurrentUser(this ControllerBase controllerBase)
        {
            return CurrentUser(controllerBase.HttpContext.User);
        }




        public static string CurrentJwt(this ControllerBase controllerBase)
        {
            return controllerBase.HttpContext.GetTokenAsync("Bearer", "access_token").Result;
        }
          
        public static string CurrentUser(this ClaimsPrincipal user)
        {
            return CurrentUser(user.Claims);
        }

        public static string CurrentUser(this IEnumerable<Claim> claims)
        {
            var sid = claims
                .FirstOrDefault(c => c.Type == ClaimTypes.Sid)?.Value;

            return sid;
        }
        // helper methods
        public static void SetTokenCookie(this ControllerBase controllerBase, string token)
        {
            var cookieOptions = new CookieOptions
            {
                HttpOnly = true,
                Expires = DateTime.UtcNow.AddDays(7)
            };

            controllerBase.Response.Cookies.Append("refreshToken", token, cookieOptions);
        }

        public static void RemoveTokenCookie(this ControllerBase controllerBase)
        {
            controllerBase.Response.Cookies.Delete("refreshToken");
        }

        public static string IpAddress(this ControllerBase controllerBase)
        {
            if (controllerBase.Request.Headers.ContainsKey("X-Forwarded-For"))
                return controllerBase.Request.Headers["X-Forwarded-For"];
            else
                return controllerBase.HttpContext.Connection.RemoteIpAddress.MapToIPv4().ToString();
        }

        public static string AccessToken(this ControllerBase controllerBase)
        {
            return AccessToken(controllerBase.HttpContext);
        }
        public static string AccessToken(this HttpContext httpContext)
        {
            return httpContext
                .GetTokenAsync("Bearer", "access_token").Result;
        }

        public static string InnerMessage(this Exception ex)
        {
            if (null != ex.InnerException)
            {
                return InnerMessage(ex.InnerException);
            }

            return (ex.Message);
        }

        public static void WriteErrorConsoleLine(string val, Exception ex)
        {
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine($"error: {val}", InnerMessage(ex));
            Console.ResetColor();
        }
    }
}
